package demo.db.elasticSearch.highClient;

import java.io.IOException;

import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.MatchPhraseQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <h1>Java High Level REST Client</h1>
 * 
 * Elastic Search支持很多查询方式，其中一种就是DSL，它是把请求写在JSON里面，然后进行相关的查询。
 * 
 */
public class DomainSpecificLanguageDemo {

    private static Logger logger = LoggerFactory.getLogger(DomainSpecificLanguageDemo.class);

    /**
     * <pre>
    {
    "query": {
    "match_all": {}
    }
    }
     * </pre>
     */
    @Test
    public void matchAll() {
        String index = "slow_redis_index_alias";
        MatchAllQueryBuilder matchQueryBuilder = QueryBuilders.matchAllQuery();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(matchQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(index);
        searchRequest.source(searchSourceBuilder);
        try (RestHighLevelClient client = RestHighLevelClientDemo.getClient()) {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            EsUtils.printSearchResponse(searchResponse);
        } catch (IOException e) {
            logger.error("", e);
        }
    }

    /**
     * <pre>
     * {
    "query" : {
        "match" : {
            "last_name" : "Smith"
        }
    }
    }
     * </pre>
     */
    @Test
    public void search1() {
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("last_name", "Smith");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(matchQueryBuilder);
        SearchRequest searchRequest = new SearchRequest("megacorp");
        searchRequest.types("employee");
        searchRequest.source(searchSourceBuilder);
        try (RestHighLevelClient client = RestHighLevelClientDemo.getClient()) {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            EsUtils.printSearchResponse(searchResponse);
        } catch (IOException e) {
            logger.error("", e);
        }
    }

    /**
     * 结构化搜索
     * 
     * <pre>
     * {
    "query" : {
        "bool": {
            "must": {
                "match" : {
                    "last_name" : "smith" 
                }
            },
            "filter": {
                "range" : {
                    "age" : { "gt" : 30 } 
                }
            }
        }
    }
    }
     * </pre>
     */
    @Test
    public void search2() {
        SearchRequest searchRequest = new SearchRequest("megacorp");
        searchRequest.types("employee");

        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        boolQueryBuilder.must(QueryBuilders.matchQuery("last_name", "Smith"));
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("age").gt(30));

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(boolQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        try (RestHighLevelClient client = RestHighLevelClientDemo.getClient()) {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            EsUtils.printSearchResponse(searchResponse);
        } catch (IOException e) {
            logger.error("", e);
        }
    }

    /**
     * 全文搜索
     * 
     * <pre>
     * {
    "query" : {
        "match" : {
            "about" : "rock climbing"
        }
    }
    }
     * </pre>
     * 
     * Elasticsearch 默认按照相关性得分排序，即每个文档跟查询的匹配程度。 Elasticsearch中的 相关性
     * 概念非常重要，也是完全区别于传统关系型数据库的一个概念，数据库中的一条记录要么匹配要么不匹配。
     */
    @Test
    public void matchQuery() {
        SearchRequest searchRequest = new SearchRequest("megacorp");
        searchRequest.types("employee");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("about", "rock climbing");
        searchSourceBuilder.query(matchQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        try (RestHighLevelClient client = RestHighLevelClientDemo.getClient()) {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            EsUtils.printSearchResponse(searchResponse);
        } catch (IOException e) {
            logger.error("", e);
        }
    }

    /**
     * 短语搜索
     * 
     * <pre>
     * {
    "query" : {
        "match_phrase" : {
            "about" : "rock climbing"
        }
    }
    }
     * </pre>
     */
    @Test
    public void matchPhraseQueryDemo() {
        SearchRequest searchRequest = new SearchRequest("megacorp");
        searchRequest.types("employee");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery("about", "rock climbing");
        searchSourceBuilder.query(matchPhraseQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        try (RestHighLevelClient client = RestHighLevelClientDemo.getClient()) {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            EsUtils.printSearchResponse(searchResponse);
        } catch (IOException e) {
            logger.error("", e);
        }
    }

    /**
     * 高亮搜索
     * 
     * <pre>
     * {
    "query" : {
        "match_phrase" : {
            "about" : "rock climbing"
        }
    },
    "highlight": {
        "fields" : {
            "about" : {}
        }
    }
    }
     * </pre>
     */
    @Test
    public void matchPhraseHighlightQuery2() {
        SearchRequest searchRequest = new SearchRequest("megacorp");
        searchRequest.types("employee");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery("about", "rock climbing");
        searchSourceBuilder.query(matchPhraseQueryBuilder);

        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("about");
        searchSourceBuilder.highlighter(highlightBuilder);
        searchRequest.source(searchSourceBuilder);
        try (RestHighLevelClient client = RestHighLevelClientDemo.getClient()) {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            EsUtils.printSearchResponse(searchResponse);
        } catch (IOException e) {
            logger.error("", e);
        }
    }
}
